home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / dflt14.zip / NORMAL.C < prev    next >
Text File  |  1992-07-29  |  33KB  |  1,084 lines

  1. /* ------------- normal.c ------------ */
  2.  
  3. #include "dflat.h"
  4.  
  5. #ifdef INCLUDE_MULTI_WINDOWS
  6. static void near PaintOverLappers(WINDOW wnd);
  7. static void near PaintUnderLappers(WINDOW wnd);
  8. #endif
  9.  
  10. static BOOL InsideWindow(WINDOW, int, int);
  11. static void TerminateMoveSize(void);
  12. static void SaveBorder(RECT);
  13. static void RestoreBorder(RECT);
  14. static void GetVideoBuffer(WINDOW);
  15. static void PutVideoBuffer(WINDOW);
  16. #ifdef INCLUDE_MINIMIZE
  17. static RECT PositionIcon(WINDOW);
  18. #endif
  19. static void near dragborder(WINDOW, int, int);
  20. static void near sizeborder(WINDOW, int, int);
  21. static int px = -1, py = -1;
  22. static int diff;
  23. static struct window dwnd = {DUMMY, NULL, NormalProc,
  24.                                 {-1,-1,-1,-1}};
  25. static int *Bsave;
  26. static int Bht, Bwd;
  27. BOOL WindowMoving;
  28. BOOL WindowSizing;
  29. /* -------- array of class definitions -------- */
  30. CLASSDEFS classdefs[] = {
  31.     #undef ClassDef
  32.     #define ClassDef(c,b,p,a) {b,p,a},
  33.     #include "classes.h"
  34. };
  35. WINDOW HiddenWindow;
  36.  
  37. /* --------- CREATE_WINDOW Message ---------- */
  38. static void CreateWindowMsg(WINDOW wnd)
  39. {
  40.     AppendWindow(wnd);
  41.     if (!SendMessage(NULL, MOUSE_INSTALLED, 0, 0))
  42.         ClearAttribute(wnd, VSCROLLBAR | HSCROLLBAR);
  43.     if (TestAttribute(wnd, SAVESELF) && isVisible(wnd))
  44.         GetVideoBuffer(wnd);
  45. }
  46.  
  47. /* --------- SHOW_WINDOW Message ---------- */
  48. static void ShowWindowMsg(WINDOW wnd, PARAM p1, PARAM p2)
  49. {
  50.     if (GetParent(wnd) == NULL || isVisible(GetParent(wnd)))    {
  51.         WINDOW cwnd;
  52.         if (TestAttribute(wnd, SAVESELF) &&
  53.                         wnd->videosave == NULL)
  54.             GetVideoBuffer(wnd);
  55.         SetVisible(wnd);
  56.         SendMessage(wnd, PAINT, 0, TRUE);
  57.         SendMessage(wnd, BORDER, 0, 0);
  58.         /* --- show the children of this window --- */
  59.         cwnd = FirstWindow(wnd);
  60.         while (cwnd != NULL)    {
  61.             if (cwnd->condition != ISCLOSING)
  62.                 SendMessage(cwnd, SHOW_WINDOW, p1, p2);
  63.             cwnd = NextWindow(cwnd);
  64.         }
  65.     }
  66. }
  67.  
  68. /* --------- HIDE_WINDOW Message ---------- */
  69. static void HideWindowMsg(WINDOW wnd)
  70. {
  71.     if (isVisible(wnd))    {
  72.         ClearVisible(wnd);
  73.         /* --- paint what this window covered --- */
  74.         if (TestAttribute(wnd, SAVESELF))
  75.             PutVideoBuffer(wnd);
  76. #ifdef INCLUDE_MULTI_WINDOWS
  77.         else
  78.             PaintOverLappers(wnd);
  79. #endif
  80.     }
  81. }
  82.  
  83. /* --------- KEYBOARD Message ---------- */
  84. static BOOL KeyboardMsg(WINDOW wnd, PARAM p1, PARAM p2)
  85. {
  86.     if (WindowMoving || WindowSizing)    {
  87.         /* -- move or size a window with keyboard -- */
  88.         int x, y;
  89.         x=WindowMoving?GetLeft(&dwnd):GetRight(&dwnd);
  90.         y=WindowMoving?GetTop(&dwnd):GetBottom(&dwnd);
  91.         switch ((int)p1)    {
  92.             case ESC:
  93.                 TerminateMoveSize();
  94.                 return TRUE;
  95.             case UP:
  96.                 if (y)
  97.                     --y;
  98.                 break;
  99.             case DN:
  100.                 if (y < SCREENHEIGHT-1)
  101.                     y++;
  102.                 break;
  103.             case FWD:
  104.                 if (x < SCREENWIDTH-1)
  105.                     x++;
  106.                 break;
  107.             case BS:
  108.                 if (x)
  109.                     --x;
  110.                 break;
  111.             case '\r':
  112.                 SendMessage(wnd,BUTTON_RELEASED,x,y);
  113.             default:
  114.                 return TRUE;
  115.         }
  116.         /* -- use the mouse functions to move/size - */
  117.         SendMessage(wnd, MOUSE_CURSOR, x, y);
  118.         SendMessage(wnd, MOUSE_MOVED, x, y);
  119.         return TRUE;
  120.     }
  121.     switch ((int)p1)    {
  122.         case F1:
  123.             SendMessage(wnd, COMMAND, ID_HELP, 0);
  124.             return TRUE;
  125.         case ' ':
  126.             if ((int)p2 & ALTKEY)
  127.                 if (TestAttribute(wnd, HASTITLEBAR))
  128.                     if (TestAttribute(wnd, CONTROLBOX))
  129.                         BuildSystemMenu(wnd);
  130.             return TRUE;
  131.         case CTRL_F4:
  132.             if (TestAttribute(wnd, CONTROLBOX))    {
  133.                 SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  134.                 SkipApplicationControls();
  135.                 return TRUE;
  136.             }
  137.             break;
  138.         default:
  139.             break;
  140.     }
  141.     return FALSE;
  142. }
  143.  
  144. /* --------- COMMAND Message ---------- */
  145. static void CommandMsg(WINDOW wnd, PARAM p1)
  146. {
  147.     switch ((int)p1)    {
  148.         case ID_HELP:
  149.             DisplayHelp(wnd,ClassNames[GetClass(wnd)]);
  150.             break;
  151. #ifdef INCLUDE_RESTORE
  152.         case ID_SYSRESTORE:
  153.             SendMessage(wnd, RESTORE, 0, 0);
  154.             break;
  155. #endif
  156.         case ID_SYSMOVE:
  157.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  158.                 (PARAM) &dwnd);
  159.             SendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
  160.                 (PARAM) &dwnd);
  161.             SendMessage(wnd, MOUSE_CURSOR,
  162.                 GetLeft(wnd), GetTop(wnd));
  163.             WindowMoving = TRUE;
  164.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  165.             break;
  166.         case ID_SYSSIZE:
  167.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  168.                 (PARAM) &dwnd);
  169.             SendMessage(wnd, CAPTURE_KEYBOARD, TRUE,
  170.                 (PARAM) &dwnd);
  171.             SendMessage(wnd, MOUSE_CURSOR,
  172.                 GetRight(wnd), GetBottom(wnd));
  173.             WindowSizing = TRUE;
  174.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  175.             break;
  176. #ifdef INCLUDE_MINIMIZE
  177.         case ID_SYSMINIMIZE:
  178.             SendMessage(wnd, MINIMIZE, 0, 0);
  179.             break;
  180. #endif
  181. #ifdef INCLUDE_MAXIMIZE
  182.         case ID_SYSMAXIMIZE:
  183.             SendMessage(wnd, MAXIMIZE, 0, 0);
  184.             break;
  185. #endif
  186.         case ID_SYSCLOSE:
  187.             SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  188.             SkipApplicationControls();
  189.             break;
  190.         default:
  191.             break;
  192.     }
  193. }
  194.  
  195. /* --------- SETFOCUS Message ---------- */
  196. static void SetFocusMsg(WINDOW wnd, PARAM p1)
  197. {
  198.     RECT rc = {0,0,0,0};
  199.     if (p1 && wnd != NULL && inFocus != wnd)    {
  200.         WINDOW this, thispar;
  201.         WINDOW that, thatpar;
  202.  
  203.         WINDOW cwnd = wnd, fwnd = GetParent(wnd);
  204.         /* ---- post focus in ancestors ---- */
  205.         while (fwnd != NULL)    {
  206.             fwnd->childfocus = cwnd;
  207.             cwnd = fwnd;
  208.             fwnd = GetParent(fwnd);
  209.         }
  210.         /* ---- de-post focus in self and children ---- */
  211.         fwnd = wnd;
  212.         while (fwnd != NULL)    {
  213.             cwnd = fwnd->childfocus;
  214.             fwnd->childfocus = NULL;
  215.             fwnd = cwnd;
  216.         }
  217.  
  218.         this = wnd;
  219.         that = thatpar = inFocus;
  220.  
  221.         /* ---- find common ancestor of prev focus and this window --- */
  222.         while (thatpar != NULL)    {
  223.             thispar = wnd;
  224.             while (thispar != NULL)    {
  225.                 if (thispar == thatpar)    {
  226.                     /* ---- don't repaint if SAVESELF window had focus ---- */
  227.                     if (this != that && TestAttribute(that, SAVESELF))
  228.                         that = thatpar = NULL;
  229.                     break;
  230.                 }
  231.                 this = thispar;
  232.                 thispar = GetParent(thispar);
  233.             }
  234.             if (thispar != NULL)
  235.                 break;
  236.             that = thatpar;
  237.             thatpar = GetParent(thatpar);
  238.         }
  239.         if (inFocus != NULL)
  240.             SendMessage(inFocus, SETFOCUS, FALSE, 0);
  241.         inFocus = wnd;
  242.         if (that != NULL && isVisible(wnd))    {
  243.             rc = subRectangle(WindowRect(that), WindowRect(this));
  244.             if (!ValidRect(rc))    {
  245.                 if (ApplicationWindow != NULL)    {
  246.                     WINDOW fwnd = FirstWindow(ApplicationWindow);
  247.                     while (fwnd != NULL)    {
  248.                         if (!isAncestor(wnd, fwnd))    {
  249.                             rc = subRectangle(WindowRect(wnd),WindowRect(fwnd));
  250.                             if (ValidRect(rc))
  251.                                 break;
  252.                         }
  253.                         fwnd = NextWindow(fwnd);
  254.                     }
  255.                 }
  256.             }
  257.         }
  258.         if (that != NULL && !ValidRect(rc) && isVisible(wnd))    {
  259.             SendMessage(wnd, BORDER, 0, 0);
  260.             this = NULL;
  261.         }
  262.         ReFocus(wnd);
  263.         if (this != NULL)
  264.             SendMessage(this, SHOW_WINDOW, 0, 0);
  265.     }
  266.     else if (!p1 && inFocus == wnd)    {
  267.         /* -------- clearing focus --------- */
  268.         inFocus = NULL;
  269.         SendMessage(wnd, BORDER, 0, 0);
  270.     }
  271. }
  272.  
  273. /* --------- DOUBLE_CLICK Message ---------- */
  274. static void DoubleClickMsg(WINDOW wnd, PARAM p1, PARAM p2)
  275. {
  276.     int mx = (int) p1 - GetLeft(wnd);
  277.     int my = (int) p2 - GetTop(wnd);
  278.     if (!WindowSizing && !WindowMoving)    {
  279.         if (HitControlBox(wnd, mx, my))    {
  280.             PostMessage(wnd, CLOSE_WINDOW, 0, 0);
  281.             SkipApplicationControls();
  282.         }
  283.     }
  284. }
  285.  
  286. /* --------- LEFT_BUTTON Message ---------- */
  287. static void LeftButtonMsg(WINDOW wnd, PARAM p1, PARAM p2)
  288. {
  289.     int mx = (int) p1 - GetLeft(wnd);
  290.     int my = (int) p2 - GetTop(wnd);
  291.     if (WindowSizing || WindowMoving)
  292.         return;
  293.     if (HitControlBox(wnd, mx, my))    {
  294.         BuildSystemMenu(wnd);
  295.         return;
  296.     }
  297.     if (my == 0 && mx > -1 && mx < WindowWidth(wnd))  {
  298.         /* ---------- hit the top border -------- */
  299.         if (TestAttribute(wnd, MINMAXBOX) &&
  300.                 TestAttribute(wnd, HASTITLEBAR))  {
  301.             if (mx == WindowWidth(wnd)-2)    {
  302.                 if (wnd->condition != ISRESTORED)
  303.                     /* --- hit the restore box --- */
  304.                     SendMessage(wnd, RESTORE, 0, 0);
  305. #ifdef INCLUDE_MAXIMIZE
  306.                 else
  307.                     /* --- hit the maximize box --- */
  308.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  309. #endif
  310.                 return;
  311.             }
  312. #ifdef INCLUDE_MINIMIZE
  313.             if (mx == WindowWidth(wnd)-3)    {
  314.                 /* --- hit the minimize box --- */
  315.                 if (wnd->condition != ISMINIMIZED)
  316.                     SendMessage(wnd, MINIMIZE, 0, 0);
  317.                 return;
  318.             }
  319. #endif
  320.         }
  321. #ifdef INCLUDE_MAXIMIZE
  322.         if (wnd->condition == ISMAXIMIZED)
  323.             return;
  324. #endif
  325.         if (TestAttribute(wnd, MOVEABLE))    {
  326.             WindowMoving = TRUE;
  327.             px = mx;
  328.             py = my;
  329.             diff = (int) mx;
  330.             SendMessage(wnd, CAPTURE_MOUSE, TRUE,
  331.                 (PARAM) &dwnd);
  332.             dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  333.         }
  334.         return;
  335.     }
  336.     if (mx == WindowWidth(wnd)-1 &&
  337.             my == WindowHeight(wnd)-1)    {
  338.         /* ------- hit the resize corner ------- */
  339. #ifdef INCLUDE_MINIMIZE
  340.         if (wnd->condition == ISMINIMIZED)
  341.             return;
  342. #endif
  343.         if (!TestAttribute(wnd, SIZEABLE))
  344.             return;
  345. #ifdef INCLUDE_MAXIMIZE
  346.         if (wnd->condition == ISMAXIMIZED)    {
  347.             if (GetParent(wnd) == NULL)
  348.                 return;
  349.             if (TestAttribute(GetParent(wnd),HASBORDER))
  350.                 return;
  351.             /* ----- resizing a maximized window over a
  352.                     borderless parent ----- */
  353.             wnd = GetParent(wnd);
  354.         }
  355. #endif
  356.         WindowSizing = TRUE;
  357.         SendMessage(wnd, CAPTURE_MOUSE,
  358.             TRUE, (PARAM) &dwnd);
  359.         dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  360.     }
  361. }
  362.  
  363. /* --------- MOUSE_MOVED Message ---------- */
  364. static BOOL MouseMovedMsg(WINDOW wnd, PARAM p1, PARAM p2)
  365. {
  366.     if (WindowMoving)    {
  367.         int leftmost = 0, topmost = 0,
  368.             bottommost = SCREENHEIGHT-2,
  369.             rightmost = SCREENWIDTH-2;
  370.         int x = (int) p1 - diff;
  371.         int y = (int) p2;
  372.         if (GetParent(wnd) != NULL &&
  373.                 !TestAttribute(wnd, NOCLIP))    {
  374.             WINDOW wnd1 = GetParent(wnd);
  375.             topmost    = GetClientTop(wnd1);
  376.             leftmost   = GetClientLeft(wnd1);
  377.             bottommost = GetClientBottom(wnd1);
  378.             rightmost  = GetClientRight(wnd1);
  379.         }
  380.         if (x < leftmost || x > rightmost ||
  381.                 y < topmost || y > bottommost)    {
  382.             x = max(x, leftmost);
  383.             x = min(x, rightmost);
  384.             y = max(y, topmost);
  385.             y = min(y, bottommost);
  386.             SendMessage(NULL,MOUSE_CURSOR,x+diff,y);
  387.         }
  388.         if (x != px || y != py)    {
  389.             px = x;
  390.             py = y;
  391.             dragborder(wnd, x, y);
  392.         }
  393.         return TRUE;
  394.     }
  395.     if (WindowSizing)    {
  396.         sizeborder(wnd, (int) p1, (int) p2);
  397.         return TRUE;
  398.     }
  399.     return FALSE;
  400. }
  401.  
  402. #ifdef INCLUDE_MAXIMIZE
  403. /* --------- MAXIMIZE Message ---------- */
  404. static void MaximizeMsg(WINDOW wnd)
  405. {
  406.     RECT rc = {0, 0, 0, 0};
  407.     RECT holdrc;
  408.     holdrc = wnd->RestoredRC;
  409.     rc.rt = SCREENWIDTH-1;
  410.     rc.bt = SCREENHEIGHT-1;
  411.     if (GetParent(wnd))
  412.         rc = ClientRect(GetParent(wnd));
  413.     wnd->oldcondition = wnd->condition;
  414.     wnd->condition = ISMAXIMIZED;
  415.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  416.     SendMessage(wnd, MOVE,
  417.         RectLeft(rc), RectTop(rc));
  418.     SendMessage(wnd, SIZE,
  419.         RectRight(rc), RectBottom(rc));
  420.     if (wnd->restored_attrib == 0)
  421.         wnd->restored_attrib = wnd->attrib;
  422.     ClearAttribute(wnd, SHADOW);
  423.     SendMessage(wnd, SHOW_WINDOW, 0, 0);
  424.     wnd->RestoredRC = holdrc;
  425. }
  426. #endif
  427.  
  428. #ifdef INCLUDE_MINIMIZE
  429. /* --------- MINIMIZE Message ---------- */
  430. static void MinimizeMsg(WINDOW wnd)
  431. {
  432.     RECT rc;
  433.     RECT holdrc;
  434.  
  435.     holdrc = wnd->RestoredRC;
  436.     rc = PositionIcon(wnd);
  437.     wnd->oldcondition = wnd->condition;
  438.     wnd->condition = ISMINIMIZED;
  439.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  440.     SendMessage(wnd, MOVE,
  441.         RectLeft(rc), RectTop(rc));
  442.     SendMessage(wnd, SIZE,
  443.         RectRight(rc), RectBottom(rc));
  444.     if (wnd == inFocus)
  445.         SetNextFocus();
  446.     if (wnd->restored_attrib == 0)
  447.         wnd->restored_attrib = wnd->attrib;
  448.     ClearAttribute(wnd,
  449.         SHADOW | SIZEABLE | HASMENUBAR |
  450.         VSCROLLBAR | HSCROLLBAR);
  451.     SendMessage(wnd, SHOW_WINDOW, 0, 0);
  452.     wnd->RestoredRC = holdrc;
  453. }
  454. #endif
  455.  
  456. #ifdef INCLUDE_RESTORE
  457. /* --------- RESTORE Message ---------- */
  458. static void RestoreMsg(WINDOW wnd)
  459. {
  460.     RECT holdrc;
  461.     holdrc = wnd->RestoredRC;
  462.     wnd->oldcondition = wnd->condition;
  463.     wnd->condition = ISRESTORED;
  464.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  465.     wnd->attrib = wnd->restored_attrib;
  466.     wnd->restored_attrib = 0;
  467.     SendMessage(wnd, MOVE, wnd->RestoredRC.lf,
  468.         wnd->RestoredRC.tp);
  469.     wnd->RestoredRC = holdrc;
  470.     SendMessage(wnd, SIZE, wnd->RestoredRC.rt,
  471.         wnd->RestoredRC.bt);
  472.     if (wnd != inFocus)
  473.         SendMessage(wnd, SETFOCUS, TRUE, 0);
  474.     else
  475.         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  476. }
  477. #endif
  478.  
  479. /* --------- MOVE Message ---------- */
  480. static void MoveMsg(WINDOW wnd, PARAM p1, PARAM p2)
  481. {
  482.     WINDOW cwnd;
  483.     BOOL wasVisible = isVisible(wnd);
  484.     int xdif = (int) p1 - wnd->rc.lf;
  485.     int ydif = (int) p2 - wnd->rc.tp;
  486.  
  487.     if (xdif == 0 && ydif == 0)
  488.         return;
  489.     if (wasVisible)
  490.         SendMessage(wnd, HIDE_WINDOW, 0, 0);
  491.     wnd->rc.lf = (int) p1;
  492.     wnd->rc.tp = (int) p2;
  493.     wnd->rc.rt = GetLeft(wnd)+WindowWidth(wnd)-1;
  494.     wnd->rc.bt = GetTop(wnd)+WindowHeight(wnd)-1;
  495.     if (wnd->condition == ISRESTORED)
  496.         wnd->RestoredRC = wnd->rc;
  497.  
  498.     cwnd = FirstWindow(wnd);
  499.     while (cwnd != NULL)    {
  500.         SendMessage(cwnd, MOVE, cwnd->rc.lf+xdif, cwnd->rc.tp+ydif);
  501.         cwnd = NextWindow(cwnd);
  502.     }
  503.     if (wasVisible)
  504.         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  505. }
  506.  
  507. /* --------- SIZE Message ---------- */
  508. static void SizeMsg(WINDOW wnd, PARAM p1, PARAM p2)
  509. {
  510.     BOOL wasVisible = isVisible(wnd);
  511.     WINDOW cwnd;
  512.     RECT rc;
  513.     int xdif = (int) p1 - wnd->rc.rt;
  514.     int ydif = (int) p2 - wnd->rc.bt;
  515.  
  516.     if (xdif == 0 && ydif == 0)
  517.         return;
  518.     if (wasVisible)
  519.         SendMessage(wnd, HIDE_WINDOW, 0, 0);
  520.     wnd->rc.rt = (int) p1;
  521.     wnd->rc.bt = (int) p2;
  522.     wnd->ht = GetBottom(wnd)-GetTop(wnd)+1;
  523.     wnd->wd = GetRight(wnd)-GetLeft(wnd)+1;
  524.  
  525.     if (wnd->condition == ISRESTORED)
  526.         wnd->RestoredRC = WindowRect(wnd);
  527.  
  528. #ifdef INCLUDE_MAXIMIZE
  529.     rc = ClientRect(wnd);
  530.  
  531.     cwnd = FirstWindow(wnd);
  532.     while (cwnd != NULL)    {
  533.         if (cwnd->condition == ISMAXIMIZED)
  534.             SendMessage(cwnd, SIZE, RectRight(rc), RectBottom(rc));
  535.         cwnd = NextWindow(cwnd);
  536.     }
  537.  
  538. #endif
  539.     if (wasVisible)
  540.         SendMessage(wnd, SHOW_WINDOW, 0, 0);
  541. }
  542.  
  543. /* --------- CLOSE_WINDOW Message ---------- */
  544. static void CloseWindowMsg(WINDOW wnd)
  545. {
  546.     WINDOW cwnd;
  547.     wnd->condition = ISCLOSING;
  548.     if (wnd->PrevMouse != NULL)
  549.         SendMessage(wnd, RELEASE_MOUSE, 0, 0);
  550.     if (wnd->PrevKeyboard != NULL)
  551.         SendMessage(wnd, RELEASE_KEYBOARD, 0, 0);
  552.     /* ----------- hide this window ------------ */
  553.     SendMessage(wnd, HIDE_WINDOW, 0, 0);
  554.     /* --- close the children of this window --- */
  555.  
  556.     cwnd = LastWindow(wnd);
  557.     while (cwnd != NULL)    {
  558.         if (inFocus == cwnd)
  559.             inFocus = wnd;
  560.         SendMessage(cwnd,CLOSE_WINDOW,0,0);
  561.         cwnd = LastWindow(wnd);
  562.     }
  563.  
  564.     /* --- change focus if this window had it -- */
  565.     if (wnd == inFocus)
  566.         SetPrevFocus();
  567.     /* -- free memory allocated to this window - */
  568.     if (wnd->title != NULL)
  569.         free(wnd->title);
  570.     if (wnd->videosave != NULL)
  571.         free(wnd->videosave);
  572.     /* -- remove window from parent's list of children -- */
  573.     RemoveWindow(wnd);
  574.     if (wnd == inFocus)
  575.         inFocus = NULL;
  576.     free(wnd);
  577. }
  578.  
  579. /* ---- Window-processing module for NORMAL window class ---- */
  580. int NormalProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  581. {
  582.     switch (msg)    {
  583.         case CREATE_WINDOW:
  584.             CreateWindowMsg(wnd);
  585.             break;
  586.         case SHOW_WINDOW:
  587.             ShowWindowMsg(wnd, p1, p2);
  588.             break;
  589.         case HIDE_WINDOW:
  590.             HideWindowMsg(wnd);
  591.             break;
  592.         case DISPLAY_HELP:
  593.             DisplayHelp(wnd, (char *)p1);
  594.             break;
  595.         case INSIDE_WINDOW:
  596.             return InsideWindow(wnd, (int) p1, (int) p2);
  597.         case KEYBOARD:
  598.             if (KeyboardMsg(wnd, p1, p2))
  599.                 return TRUE;
  600.             /* ------- fall through ------- */
  601.         case ADDSTATUS:
  602.         case SHIFT_CHANGED:
  603.             if (GetParent(wnd) != NULL)
  604.                 PostMessage(GetParent(wnd), msg, p1, p2);
  605.             break;
  606.         case PAINT:
  607.             if (isVisible(wnd))    
  608.                 ClearWindow(wnd, (RECT *)p1, ' ');
  609.             break;
  610.         case BORDER:
  611.             if (isVisible(wnd))    {
  612.                 if (TestAttribute(wnd, HASBORDER))
  613.                     RepaintBorder(wnd, (RECT *)p1);
  614.                 else if (TestAttribute(wnd, HASTITLEBAR))
  615.                     DisplayTitle(wnd, (RECT *)p1);
  616.             }
  617.             break;
  618.         case COMMAND:
  619.             CommandMsg(wnd, p1);
  620.             break;
  621.         case SETFOCUS:
  622.             SetFocusMsg(wnd, p1);
  623.             break;
  624.         case DOUBLE_CLICK:
  625.             DoubleClickMsg(wnd, p1, p2);
  626.             break;
  627.         case LEFT_BUTTON:
  628.             LeftButtonMsg(wnd, p1, p2);
  629.             break;
  630.         case MOUSE_MOVED:
  631.             if (MouseMovedMsg(wnd, p1, p2))
  632.                 return TRUE;
  633.             break;
  634.         case BUTTON_RELEASED:
  635.             if (WindowMoving || WindowSizing)    {
  636.                 if (WindowMoving)
  637.                     PostMessage(wnd,MOVE,dwnd.rc.lf,dwnd.rc.tp);
  638.                 else
  639.                     PostMessage(wnd,SIZE,dwnd.rc.rt,dwnd.rc.bt);
  640.                 TerminateMoveSize();
  641.             }
  642.             break;
  643. #ifdef INCLUDE_MAXIMIZE
  644.         case MAXIMIZE:
  645.             if (wnd->condition != ISMAXIMIZED)
  646.                 MaximizeMsg(wnd);
  647.             break;
  648. #endif
  649. #ifdef INCLUDE_MINIMIZE
  650.         case MINIMIZE:
  651.             if (wnd->condition != ISMINIMIZED)
  652.                 MinimizeMsg(wnd);
  653.             break;
  654. #endif
  655. #ifdef INCLUDE_RESTORE
  656.         case RESTORE:
  657.             if (wnd->condition != ISRESTORED)    {
  658. #ifdef INCLUDE_MAXIMIZE
  659.                 if (wnd->oldcondition == ISMAXIMIZED)
  660.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  661.                 else
  662. #endif
  663.                     RestoreMsg(wnd);
  664.             }
  665.             break;
  666. #endif
  667.         case MOVE:
  668.             MoveMsg(wnd, p1, p2);
  669.             break;
  670.         case SIZE:    {
  671.             SizeMsg(wnd, p1, p2);
  672.             break;
  673.         }
  674.         case CLOSE_WINDOW:
  675.             CloseWindowMsg(wnd);
  676.             break;
  677.         default:
  678.             break;
  679.     }
  680.     return TRUE;
  681. }
  682. #ifdef INCLUDE_MINIMIZE
  683. /* ---- compute lower right icon space in a rectangle ---- */
  684. static RECT LowerRight(RECT prc)
  685. {
  686.     RECT rc;
  687.     RectLeft(rc) = RectRight(prc) - ICONWIDTH;
  688.     RectTop(rc) = RectBottom(prc) - ICONHEIGHT;
  689.     RectRight(rc) = RectLeft(rc)+ICONWIDTH-1;
  690.     RectBottom(rc) = RectTop(rc)+ICONHEIGHT-1;
  691.     return rc;
  692. }
  693. /* ----- compute a position for a minimized window icon ---- */
  694. static RECT PositionIcon(WINDOW wnd)
  695. {
  696.     WINDOW pwnd = GetParent(wnd);
  697.     RECT rc;
  698.     RectLeft(rc) = SCREENWIDTH-ICONWIDTH;
  699.     RectTop(rc) = SCREENHEIGHT-ICONHEIGHT;
  700.     RectRight(rc) = SCREENWIDTH-1;
  701.     RectBottom(rc) = SCREENHEIGHT-1;
  702.     if (pwnd != NULL)    {
  703.         RECT prc = WindowRect(pwnd);
  704.         WINDOW cwnd = FirstWindow(pwnd);
  705.         rc = LowerRight(prc);
  706.         /* - search for icon available location - */
  707.         while (cwnd != NULL)    {
  708.             if (cwnd->condition == ISMINIMIZED)    {
  709.                 RECT rc1;
  710.                 rc1 = WindowRect(cwnd);
  711.                 if (RectLeft(rc1) == RectLeft(rc) &&
  712.                         RectTop(rc1) == RectTop(rc))    {
  713.                     RectLeft(rc) -= ICONWIDTH;
  714.                     RectRight(rc) -= ICONWIDTH;
  715.                     if (RectLeft(rc) < RectLeft(prc)+1)   {
  716.                         RectLeft(rc) =
  717.                             RectRight(prc)-ICONWIDTH;
  718.                         RectRight(rc) =
  719.                             RectLeft(rc)+ICONWIDTH-1;
  720.                         RectTop(rc) -= ICONHEIGHT;
  721.                         RectBottom(rc) -= ICONHEIGHT;
  722.                         if (RectTop(rc) < RectTop(prc)+1)
  723.                             return LowerRight(prc);
  724.                     }
  725.                     break;
  726.                 }
  727.             }
  728.             cwnd = NextWindow(cwnd);
  729.         }
  730.     }
  731.     return rc;
  732. }
  733. #endif
  734. /* ----- terminate the move or size operation ----- */
  735. static void TerminateMoveSize(void)
  736. {
  737.     px = py = -1;
  738.     diff = 0;
  739.     SendMessage(&dwnd, RELEASE_MOUSE, TRUE, 0);
  740.     SendMessage(&dwnd, RELEASE_KEYBOARD, TRUE, 0);
  741.     RestoreBorder(dwnd.rc);
  742.     WindowMoving = WindowSizing = FALSE;
  743. }
  744. /* ---- build a dummy window border for moving or sizing --- */
  745. static void near dragborder(WINDOW wnd, int x, int y)
  746. {
  747.     RestoreBorder(dwnd.rc);
  748.     /* ------- build the dummy window -------- */
  749.     dwnd.rc.lf = x;
  750.     dwnd.rc.tp = y;
  751.     dwnd.rc.rt = dwnd.rc.lf+WindowWidth(wnd)-1;
  752.     dwnd.rc.bt = dwnd.rc.tp+WindowHeight(wnd)-1;
  753.     dwnd.ht = WindowHeight(wnd);
  754.     dwnd.wd = WindowWidth(wnd);
  755.     dwnd.parent = GetParent(wnd);
  756.     dwnd.attrib = VISIBLE | HASBORDER | NOCLIP;
  757.     InitWindowColors(&dwnd);
  758.     SaveBorder(dwnd.rc);
  759.     RepaintBorder(&dwnd, NULL);
  760. }
  761. /* ---- write the dummy window border for sizing ---- */
  762. static void near sizeborder(WINDOW wnd, int rt, int bt)
  763. {
  764.     int leftmost = GetLeft(wnd)+10;
  765.     int topmost = GetTop(wnd)+3;
  766.     int bottommost = SCREENHEIGHT-1;
  767.     int rightmost  = SCREENWIDTH-1;
  768.     if (GetParent(wnd))    {
  769.         bottommost = min(bottommost,
  770.             GetClientBottom(GetParent(wnd)));
  771.         rightmost  = min(rightmost,
  772.             GetClientRight(GetParent(wnd)));
  773.     }
  774.     rt = min(rt, rightmost);
  775.     bt = min(bt, bottommost);
  776.     rt = max(rt, leftmost);
  777.     bt = max(bt, topmost);
  778.     SendMessage(NULL, MOUSE_CURSOR, rt, bt);
  779.  
  780.     if (rt != px || bt != py)
  781.         RestoreBorder(dwnd.rc);
  782.  
  783.     /* ------- change the dummy window -------- */
  784.     dwnd.ht = bt-dwnd.rc.tp+1;
  785.     dwnd.wd = rt-dwnd.rc.lf+1;
  786.     dwnd.rc.rt = rt;
  787.     dwnd.rc.bt = bt;
  788.     if (rt != px || bt != py)    {
  789.         px = rt;
  790.         py = bt;
  791.         SaveBorder(dwnd.rc);
  792.         RepaintBorder(&dwnd, NULL);
  793.     }
  794. }
  795. #ifdef INCLUDE_MULTI_WINDOWS
  796. /* ----- adjust a rectangle to include the shadow ----- */
  797. static RECT adjShadow(WINDOW wnd)
  798. {
  799.     RECT rc;
  800.     rc = wnd->rc;
  801.     if (TestAttribute(wnd, SHADOW))    {
  802.         if (RectRight(rc) < SCREENWIDTH-1)
  803.             RectRight(rc)++;           
  804.         if (RectBottom(rc) < SCREENHEIGHT-1)
  805.             RectBottom(rc)++;
  806.     }
  807.     return rc;
  808. }
  809. /* --- repaint a rectangular subsection of a window --- */
  810. static void near PaintOverLap(WINDOW wnd, RECT rc)
  811. {
  812.     if (isVisible(wnd))    {
  813.         int isBorder, isTitle, isData;
  814.         isBorder = isTitle = FALSE;
  815.         isData = TRUE;
  816.         if (TestAttribute(wnd, HASBORDER))    {
  817.             isBorder =  RectLeft(rc) == 0 &&
  818.                         RectTop(rc) < WindowHeight(wnd);
  819.             isBorder |= RectLeft(rc) < WindowWidth(wnd) &&
  820.                         RectRight(rc) >= WindowWidth(wnd)-1 &&
  821.                         RectTop(rc) < WindowHeight(wnd);
  822.             isBorder |= RectTop(rc) == 0 &&
  823.                         RectLeft(rc) < WindowWidth(wnd);
  824.             isBorder |= RectTop(rc) < WindowHeight(wnd) &&
  825.                         RectBottom(rc) >= WindowHeight(wnd)-1 &&
  826.                         RectLeft(rc) < WindowWidth(wnd);
  827.         }
  828.         else if (TestAttribute(wnd, HASTITLEBAR))
  829.             isTitle = RectTop(rc) == 0 &&
  830.                       RectLeft(rc) > 0 &&
  831.                       RectLeft(rc)<WindowWidth(wnd)-BorderAdj(wnd);
  832.  
  833.         if (RectLeft(rc) >= WindowWidth(wnd)-BorderAdj(wnd))
  834.             isData = FALSE;
  835.         if (RectTop(rc) >= WindowHeight(wnd)-BottomBorderAdj(wnd))
  836.             isData = FALSE;
  837.         if (TestAttribute(wnd, HASBORDER))    {
  838.             if (RectRight(rc) == 0)
  839.                 isData = FALSE;
  840.             if (RectBottom(rc) == 0)
  841.                 isData = FALSE;
  842.         }
  843.         if (TestAttribute(wnd, SHADOW))
  844.             isBorder |= RectRight(rc) == WindowWidth(wnd) ||
  845.                         RectBottom(rc) == WindowHeight(wnd);
  846.         if (isData)
  847.             SendMessage(wnd, PAINT, (PARAM) &rc, TRUE);
  848.         if (isBorder)
  849.             SendMessage(wnd, BORDER, (PARAM) &rc, 0);
  850.         else if (isTitle)
  851.             DisplayTitle(wnd, &rc);
  852.     }
  853. }
  854. /* ------ paint the part of a window that is overlapped
  855.             by another window that is being hidden ------- */
  856. static void PaintOver(WINDOW wnd)
  857. {
  858.     RECT wrc, rc;
  859.     wrc = adjShadow(HiddenWindow);
  860.     rc = adjShadow(wnd);
  861.     rc = subRectangle(rc, wrc);
  862.     if (ValidRect(rc))
  863.         PaintOverLap(wnd, RelativeWindowRect(wnd, rc));
  864. }
  865. /* --- paint the overlapped parts of all children --- */
  866. static void PaintOverChildren(WINDOW pwnd)
  867. {
  868.     WINDOW cwnd = FirstWindow(pwnd);
  869.     while (cwnd != NULL)    {
  870.         if (cwnd != HiddenWindow)    {
  871.             PaintOver(cwnd);
  872.             PaintOverChildren(cwnd);
  873.         }
  874.         cwnd = NextWindow(cwnd);
  875.     }
  876. }
  877. /* -- recursive overlapping paint of parents -- */
  878. static void PaintOverParents(WINDOW wnd)
  879. {
  880.     WINDOW pwnd = GetParent(wnd);
  881.     if (pwnd != NULL)    {
  882.         PaintOverParents(pwnd);
  883.         PaintOver(pwnd);
  884.         PaintOverChildren(pwnd);
  885.     }
  886. }
  887. /* - paint the parts of all windows that a window is over - */
  888. static void near PaintOverLappers(WINDOW wnd)
  889. {
  890.     HiddenWindow = wnd;
  891.     PaintOverParents(wnd);
  892. }
  893. /* --- paint those parts of a window that are overlapped --- */
  894. static void near PaintUnderLappers(WINDOW wnd)
  895. {
  896.     WINDOW hwnd = NextWindow(wnd);
  897.     while (hwnd != NULL)    {
  898.         /* ------- test only at document window level ------ */
  899.         WINDOW pwnd = GetParent(hwnd);
  900. /*        if (pwnd == NULL || GetClass(pwnd) == APPLICATION)  */  {
  901.             /* ---- don't bother testing self ----- */
  902.             if (isVisible(hwnd) && hwnd != wnd)    {
  903.                 /* --- see if other window is descendent --- */
  904.                 while (pwnd != NULL)    {
  905.                     if (pwnd == wnd)
  906.                         break;
  907.                     pwnd = GetParent(pwnd);
  908.                 }
  909.                 /* ----- don't test descendent overlaps ----- */
  910.                 if (pwnd == NULL)    {
  911.                     /* -- see if other window is ancestor --- */
  912.                     pwnd = GetParent(wnd);
  913.                     while (pwnd != NULL)    {
  914.                         if (pwnd == hwnd)
  915.                             break;
  916.                         pwnd = GetParent(pwnd);
  917.                     }
  918.                     /* --- don't test ancestor overlaps --- */
  919.                     if (pwnd == NULL)    {
  920.                         HiddenWindow = GetAncestor(hwnd);
  921.                         ClearVisible(HiddenWindow);
  922.                         PaintOver(wnd);
  923.                         SetVisible(HiddenWindow);
  924.                     }
  925.                 }
  926.             }
  927.         }
  928.         hwnd = NextWindow(hwnd);
  929.     }
  930.     /* --------- repaint all children of this window
  931.         the same way ----------- */
  932.     hwnd = FirstWindow(wnd);
  933.     while (hwnd != NULL)    {
  934.         PaintUnderLappers(hwnd);
  935.         hwnd = NextWindow(hwnd);
  936.     }
  937. }
  938. #endif /* #ifdef INCLUDE_MULTI_WINDOWS */
  939.  
  940. /* --- save video area to be used by dummy window border --- */
  941. static void SaveBorder(RECT rc)
  942. {
  943.     RECT lrc;
  944.     int i;
  945.     int *cp;
  946.     Bht = RectBottom(rc) - RectTop(rc) + 1;
  947.     Bwd = RectRight(rc) - RectLeft(rc) + 1;
  948.     Bsave = DFrealloc(Bsave, (Bht + Bwd) * 4);
  949.  
  950.     lrc = rc;
  951.     RectBottom(lrc) = RectTop(lrc);
  952.     getvideo(lrc, Bsave);
  953.     RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  954.     getvideo(lrc, Bsave + Bwd);
  955.     cp = Bsave + Bwd * 2;
  956.     for (i = 1; i < Bht-1; i++)    {
  957.         *cp++ = GetVideoChar(RectLeft(rc),RectTop(rc)+i);
  958.         *cp++ = GetVideoChar(RectRight(rc),RectTop(rc)+i);
  959.     }
  960. }
  961. /* ---- restore video area used by dummy window border ---- */
  962. static void RestoreBorder(RECT rc)
  963. {
  964.     if (Bsave != NULL)    {
  965.         RECT lrc;
  966.         int i;
  967.         int *cp;
  968.         lrc = rc;
  969.         RectBottom(lrc) = RectTop(lrc);
  970.         storevideo(lrc, Bsave);
  971.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  972.         storevideo(lrc, Bsave + Bwd);
  973.         cp = Bsave + Bwd * 2;
  974.         for (i = 1; i < Bht-1; i++)    {
  975.             PutVideoChar(RectLeft(rc),RectTop(rc)+i, *cp++);
  976.             PutVideoChar(RectRight(rc),RectTop(rc)+i, *cp++);
  977.         }
  978.         free(Bsave);
  979.         Bsave = NULL;
  980.     }
  981. }
  982. /* ----- test if screen coordinates are in a window ---- */
  983. static BOOL InsideWindow(WINDOW wnd, int x, int y)
  984. {
  985.     RECT rc;
  986.     rc = WindowRect(wnd);
  987.     if (!TestAttribute(wnd, NOCLIP))    {
  988.         WINDOW pwnd = GetParent(wnd);
  989.         while (pwnd != NULL)    {
  990.             rc = subRectangle(rc, ClientRect(pwnd));
  991.             pwnd = GetParent(pwnd);
  992.         }
  993.     }
  994.     return InsideRect(x, y, rc);
  995. }
  996.  
  997. BOOL isDerivedFrom(WINDOW wnd, CLASS class)
  998. {
  999.     CLASS tclass = GetClass(wnd);
  1000.     while (tclass != -1)    {
  1001.         if (tclass == class)
  1002.             return TRUE;
  1003.         tclass = (classdefs[tclass].base);
  1004.     }
  1005.     return FALSE;
  1006. }
  1007.  
  1008. /* -- find the oldest document window ancestor of a window -- */
  1009. WINDOW GetAncestor(WINDOW wnd)
  1010. {
  1011.     if (wnd != NULL)    {
  1012.         while (GetParent(wnd) != NULL)    {
  1013.             if (GetClass(GetParent(wnd)) == APPLICATION)
  1014.                 break;
  1015.             wnd = GetParent(wnd);
  1016.         }
  1017.     }
  1018.     return wnd;
  1019. }
  1020.  
  1021. BOOL isVisible(WINDOW wnd)
  1022. {
  1023.     while (wnd != NULL)    {
  1024.         if (isHidden(wnd))
  1025.             return FALSE;
  1026.         wnd = GetParent(wnd);
  1027.     }
  1028.     return TRUE;
  1029. }
  1030.  
  1031. /* -- adjust a window's rectangle to clip it to its parent - */
  1032. static RECT near ClipRect(WINDOW wnd)
  1033. {
  1034.     RECT rc;
  1035.     rc = WindowRect(wnd);
  1036.     if (TestAttribute(wnd, SHADOW))    {
  1037.         RectBottom(rc)++;
  1038.         RectRight(rc)++;
  1039.     }
  1040.     return ClipRectangle(wnd, rc);
  1041. }
  1042.  
  1043. /* -- get the video memory that is to be used by a window -- */
  1044. static void GetVideoBuffer(WINDOW wnd)
  1045. {
  1046.     RECT rc;
  1047.     int ht;
  1048.     int wd;
  1049.  
  1050.     rc = ClipRect(wnd);
  1051.     ht = RectBottom(rc) - RectTop(rc) + 1;
  1052.     wd = RectRight(rc) - RectLeft(rc) + 1;
  1053.     wnd->videosave = DFrealloc(wnd->videosave, (ht * wd * 2));
  1054.     get_videomode();
  1055.     getvideo(rc, wnd->videosave);
  1056. }
  1057.  
  1058. /* -- put the video memory that is used by a window -- */
  1059. static void PutVideoBuffer(WINDOW wnd)
  1060. {
  1061.     if (wnd->videosave != NULL)    {
  1062.         RECT rc;
  1063.         rc = ClipRect(wnd);
  1064.         get_videomode();
  1065.         storevideo(rc, wnd->videosave);
  1066.         free(wnd->videosave);
  1067.         wnd->videosave = NULL;
  1068.     }
  1069. }
  1070.  
  1071. /* ------- return TRUE if awnd is an ancestor of wnd ------- */
  1072. BOOL isAncestor(WINDOW wnd, WINDOW awnd)
  1073. {
  1074.     while (wnd != NULL)    {
  1075.         if (wnd == awnd)
  1076.             return TRUE;
  1077.         wnd = GetParent(wnd);
  1078.     }
  1079.     return FALSE;
  1080. }
  1081.  
  1082.  
  1083.  
  1084.